<!-- <template>
  <div class="common-layout">
    <el-container>
      <el-aside width="200px">
        <div style="background-color: burlywood;">
            image.png
        </div>
    </el-aside>
      <el-container>
        <el-header>
            TagsView
            <TagsView></TagsView>
        </el-header>
        <el-main>
            <div ref="terminal" id="Terminal" class="xterm" style="height: 10%;width: 100%;"></div>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>
<script lang="ts" setup>
import { TagsView } from '@/components/TagsView'
import WebSocketBean from '@/util/websocket/WebSocketBean'
import { IWebSocketBeanParam } from '@/util/websocket/websocket'
import { nextTick, onMounted, ref, reactive, onUnmounted, onBeforeMount } from 'vue'
import 'xterm/css/xterm.css'
import 'xterm/lib/xterm.js'
import { IBufferRange, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker, ITerminalAddon, Terminal } from 'xterm'
import { Message } from '@/entity/entitys'
// xterm.js的插件，使终端的尺寸适合包含元素。
import { FitAddon } from 'xterm-addon-fit'
// xterm.js的附加组件，用于附加到Web Socket
import { AttachAddon } from 'xterm-addon-attach'
let wsTime: any = reactive<any>("");
//import System from '~/utils/System'
let term: Terminal = reactive<Terminal>(new Terminal({
    rows: 40, //行数，影响最小高度
    cols: 100, // 列数，影响最小宽度
    convertEol: true, //启用时，光标将设置为下一行的开头
    scrollback: 50, //终端中的滚动条回滚量
    disableStdin: false, //是否应禁用输入。
    cursorStyle: "underline", //光标样式
    cursorBlink: true, //光标闪烁
    theme: {
        foreground: "#F8F8F8",
        background: "#2D2E2C",
        cursor: "help", //设置光标

    },
    fontFamily: '"Cascadia Code", Menlo, monospace',
}));
let fitAddon: FitAddon = new FitAddon();
const terminal = ref();

// 用户输入
let command: String = reactive<String>("");
onMounted(() => {
    if ("WebSocket" in window) {
        nextTick(() => {
            userWrite();
        });
        start();
    } else {
        console.log("浏览器不支持 WebSocket..");
    }

})

onUnmounted(() => {
    close();
})
enum MessageType {
    /**
     * 收到发来的消息
     */
    Get,
    /**
     * 发送到服务器的消息
     */
    Send,
    /**
     * 通知
     */
    Message
}

const conf = reactive({
    status: '未连接',
    messagetype: {
        [MessageType.Get]: '收到',
        [MessageType.Send]: '发送',
        [MessageType.Message]: '通知'
    } as any,
    message: [] as {
        time: any
        type: MessageType
        data: any
    }[],
    url: 'ws://127.0.0.1:5555',
    send: ''
})

const addMessage = (type: MessageType, ctx: any) => {
    conf.message.push({
        time: new Date().toJSON(),
        type: type,
        data: ctx
    })
}

const sendSuffix = ''

/**
* 获取连接参数，也可以直接写入，这里是因为对地址进行了配置，所以每次连接都更新一次地址
*/
const getParam = () => {
    return {
        url: conf.url,
        needReconnect: true,
        reconnectGapTime: 3000,
        sendSuffix,
        messageSuffix: sendSuffix,
        heartSend: 'JAVA',
        heartGet: 'JAVA',
        heartGapTime: 10000,
        onopen: () => {
            addMessage(MessageType.Message, '连接成功')
        },
        onmessage: (data: any) => {
            //console.log("data.data: " + data.data.message_type)
            let message: Message = JSON.parse(data.data) as Message;
            if (message.message_type != "HEARTBEAT") {
                //sp.forEach((ctx: any) => {
                term.write('\r\n')
                writeOfColor(message.data, "0;", "37m");
                term.write('\r\n$ ')
                addMessage(MessageType.Get, message.data)
                //})
            } else {
                console.log("HEARTBEAT 心跳测试: " + message.data)
            }


        },
        onerror: () => {
            addMessage(MessageType.Message, '连接失败:' + conf.url)
        }
    } as IWebSocketBeanParam
}
interface Info {
    Message_type: string;
    data: string;
}
/**
* websocket示例，主要维护和使用对象
*/
const ws = new WebSocketBean(getParam())
const start = () => {
    // ws.start()
    ws.start(getParam())
    console.log("已建立连接：", event);
    // 输入换行符可让终端显示当前用户的工作路径
    // ws.send("\n");//这边原来是放开状态,但由于后台数据返回原因会报错,就直接注释了
    // 窗口自适应插件
    // 窗口尺寸变化时，终端尺寸自适应

    fitAddon.activate(term)
    //给新的这个ws服务使用依赖设置样式
    term.loadAddon(fitAddon);
    //给新的这个ws服务使用依赖初始化
    //term.loadAddon(attachAddon)
    term.open(terminal.value);
    // // 聚焦闪烁光标
    term.focus();
    ////先默认一次适应大小
    setTimeout(() => {
        fitAddon.fit();
    }, 1000)
    window.onresize = () => {
        fitAddon.fit();
    };
    writeDefaultInfo();
}

// 自定义终端默认展示内容
function writeDefaultInfo() {
    let defaultInfo = [
        "┌\x1b[1m terminals \x1b[0m─────────────────────────────────────────────────────────────────┐ ",
        "│                                                                            │ ",
        "│  \x1b[1;34m 欢迎使用Web Docker SSH \x1b[0m                                                  │ ",
        "│                                                                            │ ",
        "└────────────────────────────────────────────────────────────────────────────┘ ",
    ];
    // 测试颜色区间
    // let arr = Array.from({length:100},(v,i)=>v = i)
    // console.log(arr)
    // arr.map((item,i) => {
    //     defaultInfo.push(`Hello from \x1B[1;3;${i}m ${i} \x1B[0m  \u2764\ufe0f   ${i}`)
    // })
    term.write(defaultInfo.join("\n\r"));
    //writeOfColor("\n\r我是加粗斜体红色的字呀", "1;3;", "31m");
    term.write('\n\r$ ')
};
//
function writeOfColor(txt: string | ArrayBuffer | null, fontCss = "", bgColor = "") {
    // 在Linux脚本中以 \x1B[ 开始，中间前部分是样式+内容，以 \x1B[0m 结尾
    // 示例 \x1B[1;3;31m 内容 \x1B[0m
    // fontCss
    // 0;-4;字体样式（0;正常 1;加粗 2;变细 3;斜体 4;下划线）
    // bgColor
    // 30m-37m字体颜色（30m:黑色 31m:红色 32m:绿色 33m:棕色字 34m:蓝色 35m:洋红色/紫色 36m:蓝绿色/浅蓝色 37m:白色）
    // 40m-47m背景颜色（40m:黑色 41m:红色 42m:绿色 43m:棕色字 44m:蓝色 45m:洋红色/紫色 46m:蓝绿色/浅蓝色 47m:白色）
    term.write(`\x1B[${fontCss}${bgColor}${txt}\x1B[0m`);
};

// 监听输入
function userWrite() {
    term.onData((e) => {
        switch (e) {
            case "\u0003": // Ctrl+C
                term.write("^C ");
                term.write("\r\n$ ");
                break;
            case "\r": // Enter
                if (command == "clear") {
                    term.clear()
                    fitAddon.fit();
                    command = "";
                    term.write('\r\n$ ')
                } else if (command != "" && command != undefined) {
                    ws.send(JSON.stringify({ message_type: "COMMAND", data: command }));//根据后台返回的数据,需要传入一个对象,里边key值为message,并对这个对象进行序列化
                    // this.ws.send("\n");//这边原来是放开状态,但由于后台数据返回原因会报错,就直接注释了
                    command = "";
                }

                break;
            case "\u007F": // Backspace (DEL)
                // Do not delete the prompt
                console.log("{}:", term)
                term.write("\b \b");
                if (command.length > 0) {
                    command = command.substr(
                        0,
                        command.length - 1
                    );
                }
                break;
            default: // Print all other characters for demo
                if (
                    (e >= String.fromCharCode(0x20) &&
                        e <= String.fromCharCode(0x7e)) ||
                    e >= "\u00a0"
                ) {
                    command += e;
                    writeOfColor(e, "2;3;", "33m");
                    console.log("用户输入command", command);
                }
        }
    });
}
const close = () => {
    ws.dispose()
    addMessage(MessageType.Message, '关闭连接成功')
}

const sendMessage = () => {
    if (ws.status === 1) {
        const sendStatus = ws.send(conf.send)
        if (sendStatus) {
            addMessage(MessageType.Send, conf.send)
            console.log("发送成功")
        }
    } else {
        console.log("未连接")
    }
}
</script>
   -->